블로그
카테고리 이동
데이터 분석, 그 중에서 특히 '분류' 방면으로 모델을 훈련시키고자 할 때, 가장 많이 부딫히는 문제가 바로 '데이터 불균형' 이다.
훈련시키는 Train data가 어느 분류는 많고, 어느 분류는 적다면
훈련되는 모델은 당연히 데이터 개수가 많은 분류에 대해 더 많이 학습이 되었을 것이고, Test data에 대해 편향된 분류를 할 수 밖에 없다.
(무엇보다 데이터 불균형 이 있음에도 어떠한 처리를 하지 않는다면, 평가하는 사람 입장에서는 이 당연한 것을 처리를 안 했어? 라고 색안경을 끼고 분석 모델 결과를 지켜볼 수 밖에 없다. 너무나도 당연하니까)
우리가 대회에서 사용할 음성 데이터 또한 그러했다.
중립 분류는 너무 적었고, 기쁨, 분노, 슬픔 데이터는 너무 많았다.
(이걸 그대로 넣어버리면, 아마 기분의 높낮이가 장난아닌 것으로 음성을 분류하지 않을까? ㅎㅎㅎ)
음성 데이터 Train data의 개수
그래서 신뢰성이 높은 모델을 확보하기 위해 '데이터 불균형 처리' 는 필수 중의 필수였다.
그래서 데이터 불균형 처리 를 위한 몇가지 방법을 찾아보았었다.
바로 'Undersampling 언더샘플링' 과 'focal loss 포칼 로스' 이었다.
Undersampling 언더샘플링과 Oversampling 오버샘플링
Undersampling 언더샘플링과 Oversampling 오버샘플링
'언더샘플링' 과 ' 오버샘플링' 은 전혀 어렵지 않다.
언더샘플링 은 데이터 수가 많은 분류항목을 데이터 수가 가장 적은 분류항목의 수에 맞추어서 데이터를 임의적으로 추출하여
모든 분류항목의 데이터 수를 맞춘 후 학습을 진행하는 방식이다.
직관적인 처리로 이해하기도 쉽고, 성능도 어느 정도 뽑히겠지만
아무래도 학습에 쓰이는 데이터가 제한적이다보니, 학습률 자체가 좋지 못할 수 있다는 단점이 있다.
오버샘플링 의 경우에는 데이터 수가 적은 분류항목의 데이터를 복제하여 데이터가 가장 많은 분류항목의 데이터 수에 맞춘다.
이 역시 직관적이라 이해하기 쉽지만은
굳이 같은 데이터를 복제까지 시켜서 학습시켜야 하나라는 본질적인 의문이 드는 것이다.
(물론 SMOTE 와 같은 데이터를 생성하는 방법도 있지만... SMOTE를 통해 생성된 데이터는 실질 데이터는 아니기 때문에 사용에 우려가 있다.)
언더샘플링 Undersampling 코드
언더샘플링 코드 역시 어렵지 않다. imblearn 패키지 에서 RandomUnderSampler 를 불러오고 fit_resample 함수를 이용하면 끝!
그러면 이렇게 가장 데이터 수가 적었던 중립 항목으로 데이터 개수들이 맞춰짐을 볼 수 있다.
포칼 로스 focal loss
focal loss 를 언급하기 전, 물론 가중치를 조정하는 방법 을 생각치 않은 것은 아니다.
(데이터 수가 적은 분류항목에 더 큰 가중치를 부여)
다만, 가중치를 넣어서 학습을 시켰더니 오히려 Accuracy가 떨어지는 효과가 발생 했다.
데이터 수는 같으니 어차피 같은 방향으로 학습이 진행되는데, 가중치가 어느 것은 크고, 어느 것은 작으니 쉽게 수렴이 되지 않았던 것 이다.
그래서 가볍게 Skip
포칼 로스 Focal loss 는 가중치를 다르게 주는 것은 맞는데, 그 방법이 약간 다르다.
아래의 사진에서 CE 는 Cross Entropy Loss 즉 기존의 크로스 엔트로피 식 이며, FL 은 Focal loss 즉 포칼 로스 식 이다.
Cross Entropy Loss 식에서 달라진 점은 (1-Pt)^r 이 들어갔다.
이것은 Cross Entropy Loss 를 통한 학습에 있어서 Easy Example 에 대해서는 학습에 좀 더 적은 영향 을 주고, Hard Example 에 대해서는 학습에 좀 더 큰 영향을 주기 위함 이다. (1-Pt가 작아질수록 Focal loss는 줄어든다. 즉 학습에 좀 더 작은 영향을 준다.)
그리고 그 영향이라는 것을 좀 더 크게 주고 싶느냐, 작게 주고 싶느냐에 따라 r 값을 조정하면 된다.
focal loss와 cross entropy
여기서 주의해야할 점은 'Easy' 와 'Hard' 에 따라 loss가 변경되어 학습이 되는 것 이지, 학습 데이터의 수에 따라 loss가 변경되는 것이 아니다.
즉, 본질적으로 이 친구는 데이터 불균형 에 대응하기 위해 사용하는 loss라고 보기는 힘들다.
이 focal loss 는 주로 이미지 인식, 분류에 주로 쓰인다. 이미지 주요 인식 부분과 그 외 부분을 나누는 분류에서 주요 인식 부분을 인식하는 것이 모델 학습에서 어렵다보니, 이런 변형된 loss를 사용하여 학습을 하는 것이다.
논문까지 나왔으니 잘 먹혔나보다. (Focal Loss for Dense Object Detection)[Focal Loss for Dense Object Detection
The highest accuracy object detectors to date are based on a two-stage approach popularized by R-CNN, where a classifier is applied to a sparse set of candidate object locations. In contrast, one-stage detectors that are applied over a regular, dense sampling of possible object locations have the po...
arxiv.org
](https://arxiv.org/abs/1708.02002)
이 focal loss 를 적용하는 방법도 어렵지 않다.
focal_loss 패키지 에서 BinaryFocalLoss 를 불러온 후
모델링 부분에서 loss에 BinaryFocalLoss 를 입력하여 사용하면 된다. (감마와 가중치는 취사선택)
focal loss 패키지와 BinaryFocalLoss
모델링에서 focal loss 사용법, 매우 쉽다.
짜투리: stratify
빅데이터분석기사 실기글에서도 stratify 를 한번 리뷰를 했었는데,
이 stratify 는 train과 test 데이터를 나눌 때 (즉, train_test_split 을 할 때) 분류 항목별로 같은 비율로 데이터가 나뉠 수 있도록 처리를 하도록 하는 속성이다.
stratify = True 를 통해 사용이 가능하다.
결과: 일반 vs 언더샘플링 vs focal loss vs focal loss+stratify
궁금한 것은 또 못 참는다. 이 데이터의 경우 데이터 불균형 처리를 위해 어떤 방식을 쓰는 것이 좋을지 각각 돌려보았다.
각각 순서대로
① 일반 모델
② Undersampling 언더샘플링 사용 모델
③ Focal loss 포칼 로스 사용 모델
④ Focal loss + stratify 포칼 로스 와 stratify 를 함께 사용한 모델
이다.
①일반 모델 → Accuracy: 88%
②언더샘플링 Undersampling 모델 → Accuracy: 90%
③Focal loss 포칼 로스 모델 → Accuracy: 88%
④Focal loss + stratify 포칼 로스와 stratify를 동시에 사용한 모델 → Accuracy: 87%
언더샘플링 이 가장 효과적이었다. 데이터 불균형 에 대해 직접적인 조치를 하니 그럴 수 밖에 없기도 하다. 다만 이렇게 언더샘플링 을 해버리면, 모아둔 데이터를 모델 학습에 미처 활용하지 못하기 때문에 학습에 있어서 부족함이 많이 느껴질 수 있다. 그래서 모델링에서는 제외...를 해야되지 않을까 싶다.
의외인 점은 focal loss 와 일반 모델과의 accuracy가 그리 차이가 없다는 것이다. (f1 score에서 약간의 차이가 있다.) focal loss 는 데이터 수의 차이보다는 'easy example', 'hard example'로 난이도 차이가 있을 때 적용해야 효과적이지 않을까 싶다.
그리고 focal loss 에 stratify 를 적용하였더니 오히려 좋지 않은 결과가 나왔다는 것이었다. learning rate 수렴이 늦어진 것을 보니, stratify 로 층화하여 분리한 것이 오히려 가중치 학습 면에서 어렵게 만든 요인이 아니었을까 싶다.
데이터 불균형 처리 는 여기까지, 이제 음성 데이터 전처리, 고도화로 가보자
이 글쓴이가 쓴 다른 글이 궁금하다면?